package org.jackysoft.entity;

import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.struts2.json.annotations.JSON;
import org.hibernate.annotations.GenericGenerator;
import org.jackysoft.annotations.BID;
import org.jackysoft.util.SecurityGrade;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;

import com.google.common.collect.Lists;
import com.google.gson.annotations.Expose;

@Entity
@Table(name = "sysuser")
public class User extends AbstractCustomeEntity implements Authentication,
		UserDetails, Comparable<User> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6758732902889482666L;

	private String password = "12345678";
	private String repassword;
	@Expose
	private String localName;

	private Boolean enabled = true;

	private Department department;

	private Role role;

	private Collection<AcegiRole> authoritys = Lists.newArrayList();
	private AcegiRole primarySecurole;
	@Expose
	private String username;
	private Boolean accountNonExpired = true;
	private Boolean accountNonLocked = true;
	private Boolean credentialsNonExpired = true;
	private boolean removed;
	private Integer sortNum = 0;
	private  SecurityGrade  securityGrade  = SecurityGrade.非密;
	

	public User() {
	}

	// for add new user
	public User(String username, String password, Department dept, Role role,
			AcegiRole securole) {
		this.username = username;
		this.password = password;
		this.department = dept;
		this.role = role;
		this.primarySecurole = securole;
		this.getAuthoritys().add(securole);
	}

	public User(String username) {
		this.username = username;
	}

	public User(String username, String localName, boolean enabled) {
		this.username = username;
		this.localName = localName;
		this.enabled = enabled;
	}

	public User(String username, String local, Department dept, Role role,
			boolean enabled) {
		this.username = username;
		this.localName = local;
		this.department = dept;
		this.role = role;
		this.enabled = enabled;
	}

	@ManyToOne
	public Role getRole() {
		return role;
	}

	/**
	 * @param role
	 *            要设置的 role
	 */
	public void setRole(Role role) {
		this.role = role;
	}

	@ManyToOne
	
	public Department getDepartment() {
		return department;
	}

	/**
	 * @param department
	 *            要设置的 department
	 */
	public void setDepartment(Department department) {
		this.department = department;
	}

	/**
	 * @return localName
	 */
	@NotNull(message = "中文名必须提供")
	public String getLocalName() {
		return localName;
	}

	/**
	 * @param localName
	 *            要设置的 localName
	 */
	public void setLocalName(String localName) {
		this.localName = localName;
	}

	/**
	 * @param password
	 *            要设置的 password
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @return enabled
	 */
	public boolean isEnabled() {
		return enabled;
	}

	/**
	 * @param enabled
	 *            要设置的 enabled
	 */
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	@ManyToMany(targetEntity = AcegiRole.class)
	@JoinTable(name = "user_authority", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "authority_id") })
	@JSON(serialize = false)
	public Collection<AcegiRole> getAuthoritys() {
		return authoritys;
	}

	public void setAuthoritys(Collection<AcegiRole> authoritys) {
		this.authoritys = authoritys;
	}

	// ~ Methods
	// ========================================================================================================

	public boolean equals(Object rhs) {
		if (!(rhs instanceof User) || (rhs == null)) {
			return false;
		}
		User user = (User) rhs;
		return (this.getUsername().equals(user.getUsername()));
	}

	@Column(name = "storePass")
	@NotNull(message = "密码必须提供")
	@Size(min =6, max = 20, message = "密码必须在6-20位之间")
	public String getPassword() {
		return password;
	}

	@AssertTrue(message = "两次密码必须相同")
	@Transient
	public boolean isPasswordEquals() {
		if (null == getPassword() || null == getRepassword())
			return false;
		return this.getPassword().equals(getRepassword());
	}

	@Id@BID
	@GeneratedValue(generator = "agn")
	@GenericGenerator(name = "agn", strategy = "assigned")
	@Column(name = "name")
	@NotNull(message = "登录名必须提供")
	@Size(min = 4, max = 15, message = "登录名必须在4-15位之间")
	@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "登录名必须是英文半角字符")
	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

	@Transient
	@JSON(serialize = false)
	public boolean isAccountNonExpired() {
		return accountNonExpired;
	}

	@Transient
	@JSON(serialize = false)
	public boolean isAccountNonLocked() {
		return this.accountNonLocked;
	}

	@Transient
	@JSON(serialize = false)
	public boolean isCredentialsNonExpired() {
		return credentialsNonExpired;
	}

	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

	@Column(columnDefinition = "int default '0'")
	public Integer getSortNum() {
		return sortNum;
	}

	public void setSortNum(Integer sortNum) {
		this.sortNum = sortNum == null ? 0 : sortNum;
	}

	public void setAccountNonExpired(boolean accountNonExpired) {
		this.accountNonExpired = accountNonExpired;
	}

	public void setAccountNonLocked(boolean accountNonLocked) {
		this.accountNonLocked = accountNonLocked;
	}

	public void setCredentialsNonExpired(boolean credentialsNonExpired) {
		this.credentialsNonExpired = credentialsNonExpired;
	}

	@Override
	public int compareTo(User o) {
		if (o == null)return 1;
		return sort - o.sort;
	}

	@Override
	@Transient
	public Collection getAuthorities() {
		return authoritys;
	}

	public void setPrimarySecurole(AcegiRole primarySecurole) {
		this.primarySecurole = primarySecurole;
	}

	@ManyToOne
	public AcegiRole getPrimarySecurole() {
		return primarySecurole;
	}

	@Transient
	@NotNull(message = "确认密码必须提供")
	@Size(min =6, max = 20, message = "确认密码必须在6-20位之间")
	public String getRepassword() {
		return repassword;
	}

	public void setRepassword(String repassword) {
		this.repassword = repassword;
	}

	@Override
	@Transient
	public String getName() {
		return getUsername();
	}

	@Override
	@Transient
	public Object getCredentials() {
		return getPassword();
	}

	@Override
	@Transient
	public Object getDetails() {
		return null;
	}

	@Override
	@Transient
	public Object getPrincipal() {
		return this;
	}

	private boolean authed;

	@Transient
	@Override
	public boolean isAuthenticated() {
		// TODO Auto-generated method stub
		return this.authed;
	}

	@Override
	public void setAuthenticated(boolean isAuthenticated)
			throws IllegalArgumentException {
		this.authed = isAuthenticated;
	}

	public SecurityGrade getSecurityGrade() {
		return securityGrade;
	}

	public void setSecurityGrade(SecurityGrade securityGrade) {
		this.securityGrade = securityGrade;
	}

	public boolean isRemoved() {
		return removed;
	}

	public void setRemoved(boolean removed) {
		this.removed = removed;
	}

}
